using System;
using System.Collections.Generic;
using System.Text;

namespace Hoshimi
{
    public class StateMachine 
	{

		#region Variables

		public Unit owner               = null;
		protected State currentState    = null;
		protected State previousState   = null;
		protected State globalState     = null;

		#endregion

		#region Ctor

		// Inhibate the default constructor
		protected StateMachine() { }

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="owner">Unit associate with the state machine</param>
		public StateMachine( Unit owner )
		{
			this.owner = owner;
		}

		#endregion

		#region Methods

		/// <summary>
		/// Save the current state in previous state value
		/// </summary>
		public void SaveCurrentState() 
		{
			previousState = currentState;
		}

		/// <summary>
		/// Set a global state. Global state is processed before current state. 
		/// If global state changes the actual state, current state won't be process.
		/// It could be used to change the behavior of the state machine
		/// </summary>
		/// <param name="state"></param>
		public void SetGlobalState( State state ) 
		{
			globalState = state;
		}

		/// <summary>
		/// Change the state. Execute Exit() method of the actual state
		/// and Enter() method of the new state
		/// </summary>
		/// <param name="newState"></param>
		public void ChangeState( State newState ) 
		{
			if ( newState != null ) 
			{
				// change state to the new state
				currentState = newState;
			}
		}

		/// <summary>
		/// Rollback to the previous state
		/// </summary>
		public void RevertToPreviousState()
		{
			ChangeState( previousState );
		}

		/// <summary>
		/// Play a unit 's state
		/// </summary>
		/// <returns>Returns true if the state has blocked the unit for this (and only this) turn</returns>
		public bool Play() 
		{
			// if a global state exists, call its execute method
			if ( globalState != null )
				if ( globalState.Play( owner ) ) return true;

			if ( currentState == null ) return true;
			
			return currentState.Play( owner );
		}

		/// <summary>
		/// Return true if the current state is the state in parameter
		/// </summary>
		/// <param name="aState"></param>
		/// <returns></returns>
		public bool IsStateEquals( State aState ) 
		{
			return this.currentState == aState;
		}

		public override string ToString()
		{
			if ( currentState == null ) return string.Empty;

			return currentState.GetType().Name;
		}

		#endregion

	}
}
